home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / misc1 / iv26_w30.zip / SOURCES / RUBCURVE.C < prev    next >
C/C++ Source or Header  |  1992-01-16  |  14KB  |  534 lines

  1. /*
  2.  * Copyright (c) 1987, 1988, 1989 Stanford University
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Stanford not be used in advertising or
  9.  * publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  Stanford makes no representations about
  11.  * the suitability of this software for any purpose.  It is provided "as is"
  12.  * without express or implied warranty.
  13.  *
  14.  * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
  16.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  19.  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  20.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  21.  */
  22.  
  23. /*
  24.  * Rubberbanding curves.
  25.  */
  26.  
  27. #include <InterViews/painter.h>
  28. #include <InterViews/rubcurve.h>
  29. #include <math.h>
  30. #include <mem.h>
  31.  
  32. RubberEllipse::RubberEllipse (
  33.     Painter* p, Canvas* c, Coord cx, Coord cy, Coord rx, Coord ry, 
  34.     Coord offx, Coord offy
  35. ) : (p, c, offx, offy) {
  36.     centerx = cx;
  37.     centery = cy;
  38.     radiusx = rx;
  39.     radiusy = ry;    
  40.     trackx = rx;
  41.     tracky = ry;
  42. }
  43.  
  44. void RubberEllipse::GetOriginal (Coord& cx, Coord& cy, Coord& rx, Coord& ry) {
  45.     cx = centerx;
  46.     cy = centery;
  47.     rx = radiusx;
  48.     ry = radiusy;
  49. }
  50.  
  51. void RubberEllipse::GetCurrent (Coord& cx, Coord& cy, Coord& rx, Coord& ry) {
  52.     cx = centerx;
  53.     cy = centery;
  54.     rx = trackx;
  55.     ry = tracky;
  56. }
  57.  
  58. void RubberEllipse::OriginalRadii (int& xr, int& yr) {
  59.     xr = abs(radiusx - centerx);
  60.     yr = abs(radiusy - centery);
  61. }
  62.  
  63. void RubberEllipse::CurrentRadii (int& xr, int& yr) {
  64.     xr = abs(trackx - centerx);
  65.     yr = abs(tracky - centery);
  66. }
  67.  
  68. void RubberEllipse::Draw () {
  69.     Coord cx, cy, rx, ry, xr, yr;
  70.  
  71.     if (!drawn) {
  72.     GetCurrent(cx, cy, rx, ry);
  73.     CurrentRadii(xr, yr);
  74.     output->Ellipse(canvas, cx+offx, cy+offy, xr, yr);
  75.     drawn = true;
  76.     }
  77. }
  78.  
  79. /**************************************************************************/
  80.  
  81. SlidingEllipse::SlidingEllipse(
  82.     Painter* p, Canvas* c, Coord cx, Coord cy, Coord xr, Coord yr,
  83.     Coord rfx, Coord rfy, Coord offx, Coord offy
  84. ) : (p, c, cx, cy, xr, yr, offx, offy) {
  85.     refx = trackx = rfx;
  86.     refy = tracky = rfy;
  87. }
  88.  
  89. void SlidingEllipse::GetCurrent (Coord& cx, Coord& cy, Coord& xr, Coord& yr) {
  90.     Coord dx = trackx - refx;
  91.     Coord dy = tracky - refy;
  92.  
  93.     cx = centerx + dx;
  94.     cy = centery + dy;
  95.     xr = radiusx;
  96.     yr = radiusy;
  97. }
  98.  
  99. void SlidingEllipse::OriginalRadii (int& xr, int& yr) {
  100.     xr = radiusx;
  101.     yr = radiusy;
  102. }
  103.  
  104. void SlidingEllipse::CurrentRadii (int& xr, int& yr) {
  105.     xr = radiusx;
  106.     yr = radiusy;
  107. }
  108.  
  109. /*****************************************************************************/
  110.  
  111. RubberCircle::RubberCircle (
  112.     Painter* p, Canvas* c, Coord cx, Coord cy, Coord rx, Coord ry,
  113.     Coord offx, Coord offy
  114. ) : (p, c, cx, cy, rx, ry, offx, offy) {
  115.     /* nothing else to do */
  116. }
  117.  
  118. void RubberCircle::OriginalRadii (int& xr, int& yr) {
  119.     Coord dx = radiusx - centerx;
  120.     Coord dy = radiusy - centery;
  121.     int radius = round(sqrt(dx*dx + dy*dy));
  122.     xr = radius;
  123.     yr = radius;
  124. }
  125.  
  126. void RubberCircle::CurrentRadii (int& xr, int& yr) {
  127.     Coord dx = trackx - centerx;
  128.     Coord dy = tracky - centery;
  129.     int radius = round(sqrt(dx*dx + dy*dy));
  130.     xr = radius;
  131.     yr = radius;
  132. }
  133.  
  134. void RubberCircle::Draw () {
  135.     int radius;
  136.  
  137.     if (!drawn) {
  138.     CurrentRadii(radius, radius);
  139.     output->Circle(canvas, centerx + offx, centery + offy, radius);
  140.     drawn = true;
  141.     }
  142. }
  143.  
  144. /*****************************************************************************/
  145.  
  146. void RubberPointList::Copy (Coord* x, Coord* y, int n, Coord*& nx, Coord*& ny){
  147.     nx = new Coord[n];
  148.     ny = new Coord[n];
  149.     memmove(nx, x, n*sizeof(Coord));
  150.     memmove(ny, y, n*sizeof(Coord));
  151. }
  152.  
  153. RubberPointList::RubberPointList (
  154.     Painter* p, Canvas* c, Coord px[], Coord py[], int n,
  155.     Coord offx, Coord offy
  156. ) : (p, c, offx, offy) {
  157.     Copy(px, py, n, x, y);
  158.     count = n;
  159. }
  160.  
  161. RubberPointList::~RubberPointList () {
  162.     delete x;
  163.     delete y;
  164. }
  165.  
  166. /*****************************************************************************/
  167.  
  168. RubberVertex::RubberVertex (
  169.     Painter* p, Canvas* c, Coord px[], Coord py[], int n, int pt,
  170.     Coord offx, Coord offy
  171. ) : (p, c, px, py, n, offx, offy) {
  172.     rubberPt = pt;
  173.     trackx = x[rubberPt];
  174.     tracky = y[rubberPt];
  175. }
  176.  
  177. void RubberVertex::GetOriginal (Coord*& px, Coord*& py, int& n, int& pt) {
  178.     Copy(x, y, count, px, py);
  179.     n = count;
  180.     pt = rubberPt;
  181. }
  182.  
  183. void RubberVertex::GetCurrent (Coord*& px, Coord*& py, int& n, int& pt) {
  184.     Copy(x, y, count, px, py);
  185.     n = count;
  186.     pt = rubberPt;
  187.     px[rubberPt] = trackx;
  188.     py[rubberPt] = tracky;
  189. }
  190.  
  191. void RubberVertex::DrawSplineSection (
  192.     Painter* p, Canvas* c, Coord x[], Coord y[]
  193. ) {
  194.     double twicex1, twicex2, p0x, p1x, p2x, p3x, tempx;
  195.     double twicey1, twicey2, p0y, p1y, p2y, p3y, tempy;
  196.  
  197.     twicex1 = 2.0*double(x[1]);
  198.     twicey1 = 2.0*double(y[1]);
  199.     twicex2 = 2.0*double(x[2]);
  200.     twicey2 = 2.0*double(y[2]);
  201.     
  202.     p1x = (twicex1 + double(x[2])) / 3.0;
  203.     p1y = (twicey1 + double(y[2])) / 3.0;
  204.     p2x = (twicex2 + double(x[1])) / 3.0;
  205.     p2y = (twicey2 + double(y[1])) / 3.0;
  206.     tempx = (twicex1 + double(x[0])) / 3.0;
  207.     tempy = (twicey1 + double(y[0])) / 3.0;
  208.     p0x = (tempx + p1x) / 2.0;
  209.     p0y = (tempy + p1y) / 2.0;
  210.     tempx = (twicex2 + double(x[3])) / 3.0;
  211.     tempy = (twicey2 + double(y[3])) / 3.0;
  212.     p3x = (tempx + p2x) / 2.0;
  213.     p3y = (tempy + p2y) / 2.0;
  214.     p->Curve(c,
  215.         round(p0x)+offx, round(p0y)+offy, round(p1x)+offx, round(p1y)+offy,
  216.     round(p2x)+offx, round(p2y)+offy, round(p3x)+offx, round(p3y)+offy
  217.     );
  218. }
  219.  
  220. /*****************************************************************************/
  221.  
  222. RubberHandles::RubberHandles (
  223.     Painter* p, Canvas* c, Coord px[], Coord py[], int n, int pt, int size,
  224.     Coord offx, Coord offy
  225. ) : (p, c, px, py, n, pt, offx, offy) {
  226.      d = size / 2;
  227. }
  228.  
  229. void RubberHandles::Draw () {
  230.     register int i;
  231.  
  232.     if (x == nil || y == nil) {
  233.         return;
  234.     }
  235.     if (!drawn) {
  236.     for (i = 0; i < count; ++i) {
  237.         if (i == rubberPt) {
  238.         output->FillRect(canvas,
  239.             trackx - d + offx, tracky - d + offy, 
  240.             trackx + d + offx, tracky + d + offy
  241.         );
  242.         } else {
  243.         output->FillRect(canvas,
  244.             x[i] - d + offx, y[i] - d + offy,
  245.             x[i] + d + offx, y[i] + d + offy
  246.         );
  247.         }        
  248.     }
  249.     drawn = true;
  250.     }
  251. }
  252.  
  253. void RubberHandles::Track (Coord x, Coord y) {
  254.     if (x != trackx || y != tracky) {
  255.         if (drawn) {
  256.         /* erase */
  257.         output->FillRect(canvas,
  258.         trackx - d + offx, tracky - d + offy,
  259.         trackx + d + offx, tracky + d + offy
  260.         );
  261.     }
  262.     trackx = x;
  263.     tracky = y;
  264.     output->FillRect(canvas,
  265.         trackx - d + offx, tracky - d + offy,
  266.         trackx + d + offx, tracky + d + offy
  267.     );
  268.     drawn = true;
  269.     }
  270. }
  271.  
  272. /*****************************************************************************/
  273.  
  274. RubberSpline::RubberSpline (
  275.     Painter* p, Canvas* c, Coord px[], Coord py[], int n, int pt,
  276.     Coord offx, Coord offy
  277. ) : (p, c, px, py, n, pt, offx, offy) {
  278.     /* nothing else to do */
  279. }
  280.  
  281. void RubberSpline::Draw () {
  282.     register int i, j;
  283.     Coord sx[7], sy[7];
  284.  
  285.     if (x == nil || y == nil) {
  286.         return;
  287.     }
  288.     if (!drawn) {
  289.         for (i = -3; i <= 3; ++i) {
  290.             j = min(max(rubberPt + i, 0), count - 1);
  291.         if (j == rubberPt) {
  292.             sx[i + 3] = trackx;
  293.         sy[i + 3] = tracky;
  294.         } else {
  295.             sx[i + 3] = x[j];
  296.             sy[i + 3] = y[j];
  297.         }
  298.         }
  299.         DrawSplineSection(output, canvas, sx, sy);
  300.         DrawSplineSection(output, canvas, &sx[1], &sy[1]);
  301.         DrawSplineSection(output, canvas, &sx[2], &sy[2]);
  302.         DrawSplineSection(output, canvas, &sx[3], &sy[3]);
  303.     drawn = true;
  304.     }
  305. }
  306.  
  307. /*****************************************************************************/
  308.  
  309. RubberClosedSpline::RubberClosedSpline (
  310.     Painter* p, Canvas* c, Coord px[], Coord py[], int n, int pt,
  311.     Coord offx, Coord offy
  312. ) : (p, c, px, py, n, pt, offx, offy) {
  313.     /* nothing else to do */
  314. }
  315.  
  316. void RubberClosedSpline::Draw () {
  317.     register int i, j;
  318.     Coord sx[7], sy[7];
  319.     
  320.     if (x == nil || y == nil) {
  321.         return;
  322.     }
  323.     if (!drawn) {
  324.     if (count > 2) {
  325.         for (i = -3; i <= 3; ++i) {
  326.         j = (rubberPt + count + i) % count;
  327.         if (j == rubberPt) {
  328.             sx[i + 3] = trackx;
  329.             sy[i + 3] = tracky;
  330.         } else {
  331.             sx[i + 3] = x[j];
  332.             sy[i + 3] = y[j];
  333.         }
  334.         }
  335.         DrawSplineSection(output, canvas, sx, sy);
  336.         DrawSplineSection(output, canvas, &sx[1], &sy[1]);
  337.         DrawSplineSection(output, canvas, &sx[2], &sy[2]);
  338.         if (count > 3) {
  339.         DrawSplineSection(output, canvas, &sx[3], &sy[3]);
  340.         }
  341.     } else {
  342.         i = 1 - rubberPt;
  343.         output->Line(canvas, x[i], y[i], trackx, tracky);
  344.     }
  345.     drawn = true;
  346.     }
  347. }
  348.  
  349. /*****************************************************************************/
  350.  
  351. SlidingPointList::SlidingPointList (
  352.     Painter* p, Canvas* c, Coord px[], Coord py[], int n,
  353.     Coord rfx, Coord rfy, Coord offx, Coord offy
  354. ) : (p, c, px, py, n, offx, offy) {
  355.     refx = rfx;
  356.     refy = rfy;
  357.     trackx = rfx;
  358.     tracky = rfy;
  359. }
  360.  
  361. void SlidingPointList::GetOriginal (Coord*& px, Coord*& py, int& n) {
  362.     register int i;
  363.     register Coord dx = trackx - refx;
  364.     register Coord dy = tracky - refy;
  365.  
  366.     px = new Coord[count];
  367.     py = new Coord[count];
  368.     n = this->count;
  369.     for (i = 0; i < count; i++) {
  370.         px[i] = x[i] - dx;
  371.     py[i] = y[i] - dy;
  372.     }
  373. }
  374.  
  375. void SlidingPointList::GetCurrent (Coord*& px, Coord*& py, int& n) {
  376.     Copy(x, y, count, px, py);
  377.     n = count;
  378. }
  379.  
  380. void SlidingPointList::Draw () {
  381.     if (x == nil || y == nil) {
  382.         return;
  383.     }
  384.     if (!drawn) {
  385.     if (offx == 0 && offy == 0) {
  386.         output->MultiPoint(canvas, x, y, count);
  387.     } else {
  388.         register Coord* ox = new Coord[count];
  389.         register Coord* oy = new Coord[count];
  390.         for (register int i = 0; i < count; i++) {
  391.         ox[i] = x[i] + offx;
  392.         oy[i] = y[i] + offy;
  393.         }
  394.         output->MultiPoint(canvas, ox, oy, count);
  395.         delete ox;
  396.         delete oy;
  397.     }
  398.     drawn = true;
  399.     }
  400. }
  401.  
  402. void SlidingPointList::Track (Coord x0, Coord y0) {
  403.     register int i;
  404.     register Coord dx, dy;
  405.  
  406.     if (x0 != trackx || y0 != tracky) {
  407.         Erase();
  408.     dx = x0 - trackx;
  409.     dy = y0 - tracky;
  410.     for (i = 0; i < count; i++) {
  411.         x[i] += dx;
  412.         y[i] += dy;
  413.     }
  414.     trackx = x0;
  415.     tracky = y0;
  416.     Draw();
  417.     }
  418. }
  419.  
  420. /*****************************************************************************/
  421.  
  422. SlidingLineList::SlidingLineList (
  423.     Painter* p, Canvas* c, Coord px[], Coord py[], int n,
  424.     Coord rfx, Coord rfy, Coord offx, Coord offy
  425. ) : (p, c, px, py, n, rfx, rfy, offx, offy) {
  426. }
  427.  
  428. void SlidingLineList::Draw () {
  429.     if (x == nil || y == nil) {
  430.         return;
  431.     }
  432.     if (!drawn) {
  433.     if (offx == 0 && offy == 0) {
  434.         output->MultiLine(canvas, x, y, count);
  435.     } else {
  436.         register Coord* ox = new Coord[count];
  437.         register Coord* oy = new Coord[count];
  438.         for (register int i = 0; i < count; i++) {
  439.         ox[i] = x[i] + offx;
  440.         oy[i] = y[i] + offy;
  441.         }
  442.         output->MultiLine(canvas, ox, oy, count);
  443.         delete ox;
  444.         delete oy;
  445.     }
  446.     drawn = true;
  447.     }
  448. }
  449.  
  450. /**************************************************************************/
  451.  
  452. ScalingLineList::ScalingLineList (
  453.     Painter* p, Canvas* c, Coord px[], Coord py[], int n,
  454.     Coord cx, Coord cy, Coord rfx, Coord rfy, Coord offx, Coord offy
  455. ) : (p, c, px, py, n, offx, offy) {
  456.     Copy(px, py, n, newx, newy);
  457.     centerx = cx;
  458.     centery = cy;
  459.     origVal = Distance(cx, cy, rfx, rfy);
  460.     origVal = (origVal == 0) ? 1 : origVal;
  461. }
  462.  
  463. ScalingLineList::~ScalingLineList () {
  464.     delete newx;
  465.     delete newy;
  466. }
  467.  
  468. void ScalingLineList::Update () {
  469.     float factor = CurrentScaling();
  470.  
  471.     for (int i = 0; i < count; ++i) {
  472.     newx[i] = round(float(x[i] - centerx)*factor) + centerx;
  473.     newy[i] = round(float(y[i] - centery)*factor) + centery;
  474.     }
  475. }
  476.  
  477. void ScalingLineList::GetOriginal (Coord*& px, Coord*& py, int& n) {
  478.     Copy(x, y, count, px, py);
  479.     n = count;
  480. }
  481.  
  482. void ScalingLineList::GetCurrent (Coord*& px, Coord*& py, int& n) {
  483.     Copy(newx, newy, count, px, py);
  484.     n = count;
  485. }
  486.  
  487. float ScalingLineList::CurrentScaling () {
  488.     return Distance(centerx, centery, trackx, tracky) / origVal;
  489. }
  490.  
  491. void ScalingLineList::Track (Coord x, Coord y) {
  492.     if (x != trackx || y != tracky) {
  493.     Erase();
  494.     trackx = x;
  495.     tracky = y;
  496.     Update();
  497.     Draw();
  498.     }
  499. }    
  500.  
  501. void ScalingLineList::Draw () {
  502.     if (!drawn) {
  503.         output->MultiLine(canvas, newx, newy, count);
  504.         drawn = true;
  505.     }
  506. }
  507.  
  508. /**************************************************************************/
  509.  
  510. RotatingLineList::RotatingLineList (
  511.     Painter* p, Canvas* c, Coord px[], Coord py[], int n,
  512.     Coord cx, Coord cy, Coord rfx, Coord rfy, Coord offx, Coord offy
  513. ) : (p, c, px, py, n, cx, cy, rfx, rfy, offx, offy) {
  514.     origVal = Angle(cx, cy, rfx, rfy);
  515. }
  516.  
  517. void RotatingLineList::Update () {
  518.     float angle = (CurrentAngle() - origVal) * M_PI/180.0;
  519.     float cosine = cos(angle);
  520.     float sine = sin(angle);
  521.     float tx, ty;
  522.     
  523.     for (int i = 0; i < count; ++i) {
  524.     tx = float(x[i] - centerx);
  525.     ty = float(y[i] - centery);
  526.     newx[i] = round(cosine*tx - sine*ty) + centerx;
  527.     newy[i] = round(sine*tx + cosine*ty) + centery;
  528.     }
  529. }
  530.  
  531. float RotatingLineList::CurrentAngle () {
  532.     return Angle(centerx, centery, trackx, tracky);
  533. };
  534.